﻿#include "CDevice.h"
/*
	Fájl: CDevice.cpp
	Szerző: Sipos Csaba, SevN
*/


using namespace Engine;
using namespace Util;


// static metódusok és paraméterek
CDevice* CDevice::pInstance=0;

CDevice::CDevice(HWND hWnd):pD3D(0),pD3DDevice(0),hWnd(hWnd)
{

  fullscreen = true;
  
  // képernyő méret beállítása az éppen használtra
	screenWidth=GetSystemMetrics(SM_CXSCREEN);
	screenHeight=GetSystemMetrics(SM_CYSCREEN);

  initD3D();

}

CDevice::~CDevice()
{
//  delete pD3DDevice;
//  delete pD3D;
}

CDevice* CDevice::createDevice(HWND hWnd)
{
	if(0 == pInstance)
	{
		pInstance=new CDevice(hWnd);
	}
	return pInstance;
}

CDevice* CDevice::getInstance()
{
  if (0 == pInstance)
  {
    LOG_WARNING("NULL Device")
  }
	return pInstance;
}

void CDevice::destroy()
{
  if (pInstance)
  {
    delete pInstance;
    pInstance = 0;
  }
}
void CDevice::initD3D()
{
	 // D3D létrehozása
	pD3D = Direct3DCreate9( D3D_SDK_VERSION );


	ZeroMemory( &d3dpp, sizeof( d3dpp ) );

  // inicializálása teljes képernyőre
	d3dpp.Windowed = FALSE;
	d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
	d3dpp.BackBufferWidth = screenWidth;// hátsó buffer szélessége
	d3dpp.BackBufferHeight = screenHeight;// magassága

	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.hDeviceWindow = hWnd;// ablak azonosító
	d3dpp.EnableAutoDepthStencil = TRUE;
	d3dpp.AutoDepthStencilFormat =D3DFMT_D24S8;
  d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;


	// D3D eszköz létrehozása
	if( FAILED( pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
									  D3DCREATE_HARDWARE_VERTEXPROCESSING,
									  &d3dpp, &pD3DDevice ) ) )
	{
    LOG_ERROR("Hiba az DirectX eszkoz letrehozasakor! Kilepes.")
    exit(1);
	}

  LOG_INFO("Eszkoz letrehozva.")

	// culling 
  pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );

  // linear filtering
	pD3DDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
	pD3DDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
	pD3DDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );	
  pD3DDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
	// zbuffer
  pD3DDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
}


int CDevice::getScreenWidth()
{
  if (fullscreen)
  {
    return screenWidth;
  }
  else
  {
    return 1024;
  }
}

int CDevice::getScreenHeight()
{
  if (fullscreen)
  {
    return screenHeight;
  }
  else
  {
    return 768;
  }
}

void CDevice::switchScreenMode()
{
  
	if(!fullscreen)
	{
		D3DFORMAT pixelFormat = D3DFMT_X8R8G8B8;	// 24 bit színmélység
		unsigned short refreshRate = 60;			// függõleges frissítés 

		d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;// hátsó buffer képpontjainak típusa(32bit)
		d3dpp.BackBufferWidth = screenWidth;// hátsó buffer szélessége
		d3dpp.BackBufferHeight = screenHeight;// magassága

		d3dpp.Windowed         = false;

		// teljes képernyõs üzemmódban ajánlott ablakstílus
		SetWindowLongPtr(hWnd, GWL_STYLE, WS_EX_TOPMOST | WS_POPUP);

		// a WinSDK súgó azt javasolja, hogy a SetWindowLongPtr() hívást 
		// mindig kövesse a SetWindowPos() API hívása, különben a változások nem lépnek érvénybe.
		SetWindowPos(hWnd, HWND_TOP, 0, 0, screenWidth, screenHeight, SWP_NOZORDER | SWP_SHOWWINDOW);


		fullscreen = true;
	}
	// ha a jelenlegi teljes képernyõs üzemmód, akkor váltsunk ablakosra
	else
	{
		RECT rect = {0, 0, 1024, 768};
		AdjustWindowRect( &rect, WS_OVERLAPPEDWINDOW, false );
		d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
		d3dpp.BackBufferWidth  = 1024;
		d3dpp.BackBufferHeight = 768;
		d3dpp.Windowed         = true;
		
		// ablak beállítása egy megfelelõbb stílusra
		SetWindowLongPtr(hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);

		// a WinSDK súgó azt javasolja, hogy a SetWindowLongPtr() hívást 
		// mindig kövesse a SetWindowPos() API hívása, különben a változások nem lépnek érvénybe.
		SetWindowPos(hWnd, HWND_TOP, 10, 10, rect.right, rect.bottom, SWP_NOZORDER | SWP_SHOWWINDOW);

		//GameCore->setHWND( g_HWnd );

		fullscreen = false;
	}
}


void CDevice::clean()
{
	if( pD3DDevice != 0 )
		pD3DDevice->Release();

	if( pD3D != 0 )
		pD3D->Release();
}

IDirect3DDevice9* CDevice::getD3DDevice()
{
  return pD3DDevice;
}

HRESULT CDevice::resetDevice()
{
  return pD3DDevice->Reset(&d3dpp);
}
